#include "time.h"
#include "../log/easylogging++.h"
#include <QDateTime>
#include <time.h>

namespace qb{
namespace base{
    namespace{
        void WordToString(unsigned short w, int len,char* str)
        {
            for (int i = len - 1; i >= 0;i--)
            {
                char d = (char)(w % 10);
                str[i] = '0'+d;
                w = w / 10;
            }
        }
    }
    class HighResTimeSupport{
    public:
        static HighResTimeSupport& Get(){
            static HighResTimeSupport  hrts;
            return hrts;
        }
        HighResTimeSupport(){}
        inline uint64_t GetTime()
        {
            return el::base::utils::DateTime::now();
        }
    };
    void HighResTime::ToLocalTime(SYSTEMTIME& stLocal)const
    {
        QDateTime dt = QDateTime::fromMSecsSinceEpoch(m_time / 1000);
        stLocal.wYear = dt.date().year();
        stLocal.wMonth = dt.date().month();
        stLocal.wDay = dt.date().day();
        stLocal.wDayOfWeek = dt.date().dayOfWeek();
        stLocal.wHour = dt.time().hour();
        stLocal.wMinute = dt.time().minute();
        stLocal.wSecond = dt.time().second();
        stLocal.wMilliseconds = dt.time().msec();
    }
    HighResTime HighResTime::today()
    {
        return HighResTime(m_time) - todaypassed();//0:0:0?
    }
    HighResTime HighResTime::todaypassed()
    {
        SYSTEMTIME time;
        ToLocalTime(time);
        double start =((time.wHour * 3600 + time.wMinute * 60 + time.wSecond) * 1000 + time.wMilliseconds)*1000.0;
        return HighResTime(start);
    }
    BaseString HighResTime::ToString(const char* format)const
    {
        // YMD
        // hmsi
        const char* fmt = format ? format : "Y/M/D h:m:s-i";
        BaseString timestr(64);
        int len = strlen(fmt);
        SYSTEMTIME st;
        ToLocalTime(st);
        char buf[16] = { 0 };
        for (int i = 0; i < len;i++)
        {
            switch (fmt[i])
            {
            case 'Y':WordToString(st.wYear, 4, buf); timestr.append(buf, 4); break;
            case 'M':WordToString(st.wMonth, 2, buf); timestr.append(buf, 2); break;
            case 'D':WordToString(st.wDay, 2, buf); timestr.append(buf, 2); break;
            case 'h':WordToString(st.wHour, 2, buf); timestr.append(buf, 2); break;
            case 'm':WordToString(st.wMinute, 2, buf); timestr.append(buf, 2); break;
            case 's':WordToString(st.wSecond, 2, buf); timestr.append(buf, 2); break;
            case 'i':WordToString(st.wMilliseconds, 3, buf); timestr.append(buf, 3); break;
            default:timestr.push_back(fmt[i]);
                break;
            }
        }
        return timestr;
    }
    HighResTime::HighResTime() :m_time(HighResTimeSupport::Get().GetTime())
    {
    }
    uint64_t GetHighResTimeD()
    {
        return HighResTimeSupport::Get().GetTime();//微秒
    }
    unsigned int GetHighResTime()
    {
        return (unsigned int)(HighResTimeSupport::Get().GetTime()/1000); //毫秒
    }
}//namespace base;
}//namespace qb;

#ifndef _MSC_VER
unsigned long GetTickCount()
{
    struct timespec ts;
    clock_gettime(CLOCK_MONOTONIC, &ts);
    return (ts.tv_sec*1000 + ts.tv_nsec/1000000);
}
#endif